﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Practices.Unity;
using Sautom.DataAccess;
using Sautom.DataAccess.Queries;
using Sautom.DataAccess.Repositories;
using Sautom.DataAccess.UnitOfWorkAware;
using Sautom.Queries;
using Sautom.Services.Repositories;
using Sautom.Services.UnitOfWork;
using Sautom.Domain;

namespace Sautom.CompositionRoot
{
    internal sealed class UnityDependencyResolver : IDependencyResolver
    {
        private readonly IUnityContainer _unityContainer;
        public UnityDependencyResolver()
        {
            _unityContainer = new UnityContainer()
                .RegisterType<IUnitOfWorkFactory, EfUnitOfWorkFactory>()
                .RegisterType<DatabaseContext, DatabaseContext>(new PerResolveLifetimeManager())
                .RegisterInstance("currentUserName", "pavlova");
            
            IEnumerable<Type> reposInterfaces =
                Assembly.GetAssembly(typeof (IRepository<>)).GetExportedTypes().Where(
                    rec => rec.Namespace == "Sautom.Services.Repositories" && rec.IsInterface && !rec.IsGenericType);

            IEnumerable<Type> reposImplementation = Assembly.GetAssembly(typeof(RepositoryBase<>)).GetExportedTypes().Where(
                    rec => rec.Namespace == "Sautom.DataAccess.Repositories" && rec.IsClass);

            foreach (Type intrface in reposInterfaces)
            {
                Type type = reposImplementation.FirstOrDefault(rec => rec.GetInterface(intrface.Name) != null);
                if (type != null) _unityContainer.RegisterType(intrface, type);
            }

            IEnumerable<Type> findersInterfaces =
                Assembly.GetAssembly(typeof(IClientFinder)).GetExportedTypes().Where(
                    rec => rec.Namespace == "Sautom.Queries" && rec.IsInterface && !rec.IsGenericType);

            IEnumerable<Type> findersImplementation = Assembly.GetAssembly(typeof(FinderBase)).GetExportedTypes().Where(
                    rec => rec.Namespace == "Sautom.DataAccess.Queries" && rec.IsClass);

            foreach (Type intrface in findersInterfaces)
            {
                Type type = findersImplementation.FirstOrDefault(rec => rec.GetInterface(intrface.Name) != null);
                if (type != null) _unityContainer.RegisterType(intrface, type);
            }
        }

        public object Resolve(Type type)
        {
            return _unityContainer.Resolve(type);
        }

        public void Teardown(object o)
        {
            _unityContainer.Teardown(o);
        }
    }
}